#region Summary

// 
// Owner : JackieHan 
// 
// Solution : UpdateSystem
// 
// Project :Project
// 
// File : PublishManager.cs
// 
// CopyRight : Copyright © 2010-2011 Skomart Corporation, All Rights Reserved 
// 
// Summary : 发布处理类
// 
// History : 
//			2011-01-07 16:03:26	    Create 
// 

#endregion

#region Using

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security;
using System.ServiceModel;
using Jackie.Utility;
using Jackie.Utility.CustomException;
using Jackie.Update.Entities;
using Jackie.Update.Entities.Server;
using Jackie.Update.IBusiness;
using Jackie.Utility.CustomExtension;

#endregion

namespace Jackie.Update.Publish
{
    /// <summary> 
    /// 发布处理类
    /// </summary>
    public class PublishManager
    {
        private readonly PublishForm publishForm;

        public PublishManager(PublishForm form)
        {
            publishForm = form;
        }

        public void Publish(string name, string localPath, string version, string discription)
        {
            //验证版本号
            if (!JackieValidator.IsVersion(version))
                return;

            var channelFacotry = new ChannelFactory<IPublish>("publishWcfService");
            var publishServiceProxy = channelFacotry.CreateChannel();

            //检查版本号
            if(!publishServiceProxy.CheckSystemVersion(name, version))
                throw new VersionExistedException(version);
            var serverNewFiles = publishServiceProxy.GetNewFiles(name);
            var localFiles = GetLocalFile(localPath);
            localFiles.ForEach(file => file.Path = file.Path.Replace(localPath, ""));
            var updateFiles = GetUpdateFiles(localFiles, serverNewFiles);
            var serverPublishDirectory = publishServiceProxy.GetPublishDirectory(name);
            var uploadManager =
                new UploadManager(updateFiles.Where(file => file.OperateType != OperateType.Delete).ToList(),
                                  publishForm, localPath, serverPublishDirectory, version);
            if (uploadManager.Upload())
            {
                publishServiceProxy.UpdateConfig(name, new PublishLogInfo
                                                           {
                                                               Date = DateTime.Now,
                                                               Files = updateFiles,
                                                               SystemVersion = version,
                                                               Descriptions = CreateDiscription(discription)
                                                           });
            }
        }

        private IList<string> CreateDiscription(string discription)
        {
            var strs = discription.Split('\n');
            return strs.ToList();
        }

        private List<UpdateFileInfo> GetUpdateFiles(List<UpdateFileInfo> localFiles, List<UpdateFileInfo> serverNewFiles)
        {
            var updateFiles = (from localFile in localFiles
                               from serverFile in serverNewFiles
                               where localFile.Path.Equals(serverFile.Path) && !localFile.HashCode.Equals(serverFile.HashCode)
                               select localFile).ToList();
            updateFiles.ForEach(file => file.OperateType = OperateType.Update);

            var addFiles =
                localFiles.Where(localFile => !serverNewFiles.Any(serverFile => serverFile.Path == localFile.Path)).
                    ToList();
            addFiles.ForEach(file => file.OperateType = OperateType.Add);

            var deleteFiles =
                serverNewFiles.Where(serverFile => !localFiles.Any(localFile => localFile.Path == serverFile.Path)).
                    ToList();
            deleteFiles.ForEach(file => file.OperateType = OperateType.Delete);

            updateFiles.AddRange(addFiles);
            updateFiles.AddRange(deleteFiles);
            return updateFiles;
        }

        private List<UpdateFileInfo> GetLocalFile(string localPath)
        {
            var localFileInfos = new List<UpdateFileInfo>();
            var localDirectory = new DirectoryInfo(localPath);
            foreach (var childDirectory in localDirectory.GetDirectories())
            {
                localFileInfos.AddRange(GetLocalFile(childDirectory.FullName));
            }
            var localFiles = localDirectory.GetFiles().Select(file => new UpdateFileInfo
                                                                          {
                                                                              HashCode = file.GetContentHashCode(),
                                                                              Length = file.Length,
                                                                              OperateType = OperateType.Add,
                                                                              Path = file.FullName
                                                                          }).ToList();
            localFileInfos.AddRange(localFiles);
            return localFileInfos;
        }
    }
}